package com.example.netcapture.service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.netcapture.dto.PacketInfoDto;
import com.example.netcapture.entity.PacketInfo;
import com.example.netcapture.repository.PacketInfoMapper;

import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

@Service
@RequiredArgsConstructor
public class PacketQueryService {

    private final PacketInfoMapper packetInfoMapper;
    private final PcapFileParserService pcapFileParserService;

    public Page<PacketInfoDto> queryPackets(String protocol, String sourceIp, String destinationIp,
                                            Integer sourcePort, Integer destinationPort, String sessionId,
                                            LocalDateTime startTime, LocalDateTime endTime,
                                            Boolean bidirectional, int pageNo, int pageSize) {

        QueryWrapper<PacketInfo> wrapper = new QueryWrapper<>();

        if (protocol != null && !protocol.trim().isEmpty()) {
            wrapper.eq("protocol", protocol);
        }
        if (sessionId != null) {
            wrapper.eq("session_id", sessionId);
        }
        if (startTime != null) {
            wrapper.ge("capture_time", startTime);
        }
        if (endTime != null) {
            wrapper.le("capture_time", endTime);
        }

        // 处理双向过滤
        if (Boolean.TRUE.equals(bidirectional)) {
            // 双向模式：IP和端口可以匹配源或目标
            if ((sourceIp != null && !sourceIp.trim().isEmpty()) ||
                    (destinationIp != null && !destinationIp.trim().isEmpty()) ||
                    sourcePort != null || destinationPort != null) {

                wrapper.and(qw -> {
                    // 第一种情况：源IP/端口匹配输入的源条件
                    if (sourceIp != null && !sourceIp.trim().isEmpty()) {
                        qw.like("source_ip", sourceIp);
                    }
                    if (sourcePort != null) {
                        qw.eq("source_port", sourcePort);
                    }
                    if (destinationIp != null && !destinationIp.trim().isEmpty()) {
                        qw.like("destination_ip", destinationIp);
                    }
                    if (destinationPort != null) {
                        qw.eq("destination_port", destinationPort);
                    }

                    // 第二种情况：源IP/端口匹配输入的目标条件，目标IP/端口匹配输入的源条件（反向）
                    qw.or(orQw -> {
                        if (sourceIp != null && !sourceIp.trim().isEmpty()) {
                            orQw.like("destination_ip", sourceIp);
                        }
                        if (sourcePort != null) {
                            orQw.eq("destination_port", sourcePort);
                        }
                        if (destinationIp != null && !destinationIp.trim().isEmpty()) {
                            orQw.like("source_ip", destinationIp);
                        }
                        if (destinationPort != null) {
                            orQw.eq("source_port", destinationPort);
                        }
                    });
                });
            }
        } else {
            // 单向模式：保持原有逻辑
            if (sourceIp != null && !sourceIp.trim().isEmpty()) {
                wrapper.like("source_ip", sourceIp);
            }
            if (destinationIp != null && !destinationIp.trim().isEmpty()) {
                wrapper.like("destination_ip", destinationIp);
            }
            if (sourcePort != null) {
                wrapper.eq("source_port", sourcePort);
            }
            if (destinationPort != null) {
                wrapper.eq("destination_port", destinationPort);
            }
        }

        wrapper.orderByAsc("capture_time");

        Page<PacketInfo> page = new Page<>(pageNo, pageSize);
        Page<PacketInfo> result = packetInfoMapper.selectPage(page, wrapper);

        Page<PacketInfoDto> dtoPage = new Page<>();
        dtoPage.setCurrent(result.getCurrent());
        dtoPage.setSize(result.getSize());
        dtoPage.setTotal(result.getTotal());
        dtoPage.setPages(result.getPages());

        List<PacketInfoDto> dtoList = result.getRecords().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());

        dtoPage.setRecords(dtoList);

        return dtoPage;
    }

    public List<PacketInfo> getRecentPackets(int limit) {
        QueryWrapper<PacketInfo> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("capture_time").last("LIMIT " + limit);
        return packetInfoMapper.selectList(wrapper);
    }

    public PacketInfo getPacketDetail(Long id) {
        return packetInfoMapper.selectById(id);
    }

    private PacketInfoDto convertToDto(PacketInfo packet) {
        PacketInfoDto dto = new PacketInfoDto();
        dto.setId(packet.getId());
        dto.setCaptureTime(packet.getCaptureTime());
        dto.setSourceIp(packet.getSourceIp());
        dto.setDestinationIp(packet.getDestinationIp());
        dto.setSourcePort(packet.getSourcePort());
        dto.setDestinationPort(packet.getDestinationPort());
        dto.setProtocol(packet.getProtocol());
        dto.setPacketLength(packet.getPacketLength());
        dto.setHttpMethod(packet.getHttpMethod());
        dto.setHttpUrl(packet.getHttpUrl());
        dto.setHttpStatus(packet.getHttpStatus());
        dto.setTcpFlags(packet.getTcpFlags());
        dto.setNetworkInterface(packet.getNetworkInterface());

        dto.setSummary(generatePacketSummary(packet));
        dto.setSessionId(packet.getSessionId());
        dto.setPayload(packet.getPayload());
        dto.setHexData(packet.getHexData());

        return dto;
    }

    private String generatePacketSummary(PacketInfo packet) {
        StringBuilder summary = new StringBuilder();

        summary.append(packet.getProtocol());

        if (packet.getSourceIp() != null && packet.getDestinationIp() != null) {
            summary.append(" ")
                    .append(packet.getSourceIp())
                    .append(":")
                    .append(packet.getSourcePort() != null ? packet.getSourcePort() : "")
                    .append(" -> ")
                    .append(packet.getDestinationIp())
                    .append(":")
                    .append(packet.getDestinationPort() != null ? packet.getDestinationPort() : "");
        }

        if (packet.getHttpMethod() != null) {
            summary.append(" [").append(packet.getHttpMethod()).append("]");
        }

        if (packet.getHttpUrl() != null) {
            summary.append(" ").append(packet.getHttpUrl());
        }

        if (packet.getHttpStatus() != null) {
            summary.append(" [").append(packet.getHttpStatus()).append("]");
        }

        if (packet.getPacketLength() != null) {
            summary.append(" (").append(packet.getPacketLength()).append(" bytes)");
        }

        return summary.toString();
    }

    /**
     * 删除所有数据包记录
     */
    @Transactional
    public int deleteAllPackets() {
        try {
            // 先查询记录数量用于日志记录
            Long count = packetInfoMapper.selectCount(null);
            // 删除所有记录
            int deletedCount = packetInfoMapper.delete(null);

            return deletedCount;

        } catch (Exception e) {
            throw new RuntimeException("删除数据包记录失败: " + e.getMessage(), e);
        }
    }

    /**
     * 导入PCAP文件
     *
     * @param file MultipartFile对象
     * @param clearExisting 是否清空现有数据
     * @return 导入的数据包数量
     * @throws Exception 导入过程中可能出现的异常
     */
    @Transactional
    public int importPcapFile(MultipartFile file, boolean clearExisting) throws Exception {
        // 验证文件
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("PCAP文件不能为空");
        }

        // 验证文件类型
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null ||
                (!originalFilename.toLowerCase().endsWith(".pcapng") &&
                        !originalFilename.toLowerCase().endsWith(".pcap") &&
                        !originalFilename.toLowerCase().endsWith(".cap"))) {
            throw new IllegalArgumentException("不支持的文件格式，请上传PCAP文件");
        }

        // 如果选择清空现有数据
        if (clearExisting) {
            deleteAllPackets();
        }

        // 创建临时文件
        File tempFile = null;
        try {
            // 创建临时文件
            tempFile = File.createTempFile("pcap_import_", ".pcap");
            tempFile.deleteOnExit();

            // 将MultipartFile转换为File
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                fos.write(file.getBytes());
            }

            // 使用PcapFileParserService解析PCAP文件并保存到数据库
            String networkInterface = "imported_from_" + originalFilename;
            int importedCount = pcapFileParserService.parsePcapFileAndSave(tempFile.getAbsolutePath(), networkInterface);

            return importedCount;

        } catch (IOException e) {
            throw new RuntimeException("处理PCAP文件时发生IO异常: " + e.getMessage(), e);
        } finally {
            // 清理临时文件
            if (tempFile != null && tempFile.exists()) {
                try {
                    Files.deleteIfExists(tempFile.toPath());
                } catch (IOException e) {
                    // 记录警告但不抛出异常，避免掩盖主要异常
                    System.err.println("警告：无法删除临时文件: " + tempFile.getAbsolutePath());
                }
            }
        }
    }

    /**
     * 导入PCAP文件（重载方法，带最大包数量限制）
     *
     * @param file MultipartFile对象
     * @param clearExisting 是否清空现有数据
     * @param maxPackets 最大解析包数量，-1表示无限制
     * @return 导入的数据包数量
     * @throws Exception 导入过程中可能出现的异常
     */
    @Transactional
    public int importPcapFile(MultipartFile file, boolean clearExisting, int maxPackets) throws Exception {
        // 验证文件
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("PCAP文件不能为空");
        }

        // 验证文件类型
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null ||
                (!originalFilename.toLowerCase().endsWith(".pcapng") &&
                        !originalFilename.toLowerCase().endsWith(".pcap") &&
                        !originalFilename.toLowerCase().endsWith(".cap"))) {
            throw new IllegalArgumentException("不支持的文件格式，请上传PCAP文件");
        }

        // 如果选择清空现有数据
        if (clearExisting) {
            deleteAllPackets();
        }

        // 创建临时文件
        File tempFile = null;
        try {
            // 创建临时文件
            tempFile = File.createTempFile("pcap_import_", ".pcap");
            tempFile.deleteOnExit();

            // 将MultipartFile转换为File
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                fos.write(file.getBytes());
            }

            // 使用PcapFileParserService解析PCAP文件并保存到数据库
            String networkInterface = "imported_from_" + originalFilename;
            int importedCount = pcapFileParserService.parsePcapFileAndSave(tempFile.getAbsolutePath(), networkInterface, maxPackets);

            return importedCount;

        } catch (IOException e) {
            throw new RuntimeException("处理PCAP文件时发生IO异常: " + e.getMessage(), e);
        } finally {
            // 清理临时文件
            if (tempFile != null && tempFile.exists()) {
                try {
                    Files.deleteIfExists(tempFile.toPath());
                } catch (IOException e) {
                    // 记录警告但不抛出异常，避免掩盖主要异常
                    System.err.println("警告：无法删除临时文件: " + tempFile.getAbsolutePath());
                }
            }
        }
    }
}